package tool;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;

/**图片处理工具
 * Create by zekdot on 19-12-25.
 */
public class PicTool {
    private static int BLACK=0x00000000;
    private static int WHITE=0xffffffff;
    /**
     * 将一个像素点转为白色或者黑色。
     *
     * @param pixel
     * @return 转换后的像素点（黑/白）
     */
    private static int pixelConvert(int pixel) {
        int result = 0;
        //获取R/G/B
        int r = (pixel >> 16) & 0xff;
        int g = (pixel >> 8) & 0xff;
        int b = (pixel) & 0xff;

        //默认黑色
        result = BLACK;

        int tmp = r * r + g * g + b * b;
        if (tmp > 3 * 128 * 128) {
            //白色，全F
            result = WHITE;
        }

        return result;
    }

    /** 过滤其中一个点的周边的噪音
     *
     * @param image 图片
     * @param x 横坐标
     * @param y 纵坐标
     * @param f 方向
     * @param w 栈深度
     */
    private static boolean filterOneDot(BufferedImage image, int x, int y, int f, int w){
        if(w==0) return false; //如果超过了最大栈，返回
        if(x>0 && image.getRGB(x-1,y)==BLACK && f!=1){
            if(!filterOneDot(image,x-1,y,3,w-1)) return false;
        }
        if(x<image.getWidth()-1 && image.getRGB(x+1,y)==BLACK && f!=3){
            if(!filterOneDot(image,x+1,y,1,w-1)) return false;
        }
        if(y>0 && image.getRGB(x,y-1)==BLACK && f!=0){
            if(!filterOneDot(image,x,y-1,2,w-1)) return false;
        }
        if(y<image.getHeight()-1 && image.getRGB(x,y+1)==BLACK && f!=2){
            if(!filterOneDot(image,x,y+1,0,w-1)) return false;
        }
        image.setRGB(x,y,WHITE);
        return true;
    }

    /**过滤噪音
     *
     * @param image
     */
    private static void dotFilter(BufferedImage image){
        for(int i=0;i<image.getHeight();i++){
            for(int j=0;j<image.getWidth();j++){
                //逐点过滤，这里需要调用一个递归的方式来进行真正的过滤操作
                if(image.getRGB(j,i)==BLACK){
                    filterOneDot(image,j,i,-1,2);
                }
            }
        }
    }

    /**黑白化处理
     *
     * @param image
     */
    private static void whiteAndBlack(BufferedImage image){
        for(int i=0;i<image.getHeight();i++){
            for(int j=0;j<image.getWidth();j++){
                image.setRGB(j,i,pixelConvert(image.getRGB(j,i)));
            }
        }
    }
    /**获得黑白化并且切割、去噪后的子图
     *
     * @param image
     */
    private static BufferedImage[] getSubImages(BufferedImage image){
        whiteAndBlack(image);   //黑白化图片
        dotFilter(image);   //去噪
        image=image.getSubimage(4,0,52,20);
        BufferedImage[] images=new BufferedImage[4];
        for(int i=0;i<4;i++){
            images[i]=image.getSubimage(3+i*12,0,12,20);
        }
        return images;
    }
    /**根据图片得到一维数组
     *
     * @param image
     * @return
     */
    private static float[] getArrayByPic(BufferedImage image){
        float res[]=new float[240];
        for(int i=0;i<image.getHeight();i++){
            for(int j=0;j<image.getWidth();j++){
                res[i*12+j]=image.getRGB(j,i)==BLACK?0:1;
            }
        }
        return res;
    }

    /** 根据图片得到对应的二维数组
     *
     * @param image
     * @return
     */
    public static float[][] getArraysByPic(BufferedImage image){
        float res[][]=new float[4][120];
        BufferedImage[] images=getSubImages(image); //分割数组
        for(int i=0;i<4;i++){   //四次
            res[i]=getArrayByPic(images[i]);   //放入一个数组
        }

        return res;
    }

    /**在控制台打印图片数组
     *
     * @param image
     */
    public static void printPicArray(BufferedImage image){
        for(int i=0;i<image.getHeight();i++){
            for(int j=0;j<image.getWidth();j++){
                System.out.printf("%2d ",image.getRGB(j,i));
            }
            System.out.println();
        }
    }

    /**
     * 将图片写入磁盘文件
     *
     * @param imgFile 文件路径
     * @param bi BufferedImage 对象
     * @return 无
     */
    public static void writeImageToFile(String imgFile, BufferedImage bi) {
        // 写图片到磁盘上
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(imgFile
                .substring(imgFile.lastIndexOf('.') + 1));
        ImageWriter writer = (ImageWriter) writers.next();
        // 设置输出源
        File f = new File(imgFile);
        ImageOutputStream ios;

        try {
            ios = ImageIO.createImageOutputStream(f);
            writer.setOutput(ios);
            // 写入到磁盘
            writer.write(bi);
            ios.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从磁盘上获取图片
     * @param path
     * @return
     */
    public static BufferedImage getImage(String path) {
        BufferedImage image = null;
        try {
            image = ImageIO.read(new File(path));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return image;
    }
}
